﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using IMIForUnity;
using UnityEngine.UI;

public class ImiExplorer : MonoBehaviour
{

    //Parent of all Skeletons
    public GameObject skeletons;
    private List<GameObject> skeletonList = new List<GameObject>();

    //Displaying Color Image
    public RawImage colorView;

    //Displaying Depth Image
    public RawImage depthView;

	private bool CustomDepthDataProcessor = true;

    private Texture2D customDepthTex;
    private byte[] usersDepthColors;
    private float[] usersHistogramMap;

    private int skeletonCount = (int)ImiSkeleton.Index.COUNT;

    public Text label;

    private ImiManager imiManager;

    // Use this for initialization
    void Start()
    {

        Debug.Log("skeletonCount = " + skeletonCount);
        int skeletonsNum = skeletonCount;
        for (int i = 0; i < skeletonsNum; i++)
        {
            GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            sphere.transform.parent = skeletons.transform;
            sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            skeletonList.Add(sphere);
        }

        imiManager = ImiManager.GetInstance();
        imiManager.OnDeviceOpened += OnDeviceOpened;
        imiManager.OnDeviceOpened += initGestures;

        imiManager.OpenDevice();
        imiManager.SetControlPlayerChangeListener(OnMainPlayerChange);


        if (CustomDepthDataProcessor)
        {
            initCustomTexture();
        }
    }

    void initCustomTexture()
    {
        customDepthTex = new Texture2D(640, 480, TextureFormat.RGBA32, false);
        usersDepthColors = new byte[640 * 480 * 4];
        usersHistogramMap = new float[65536];
    }

    void initGestures(object sende, EventArgs args)
    {
        ImiGestureManager gestureManager = ImiGestureManager.GetInstance();
        if (gestureManager != null)
        {
            gestureManager.AddGesture(typeof(RightHandWave), (gesture,player,gevent)=> 
            {
                if(gevent == GestureEvent.Complete)
                {
                    Debug.Log("Right Hand Wave Detected!");
                }
            });

            gestureManager.AddGesture(typeof(RightHandWaveLeft), (gesture,player,gevent)=> {
                if(gevent == GestureEvent.Complete)
                {
                    Debug.Log("Right Hand Wave Left Detected!");
                }
            });

            gestureManager.AddGesture(typeof(LeftHandWaveRight),  (gesture,player,gevent)=> {
                if(gevent == GestureEvent.Complete)
                {
                    Debug.Log("Left Hand Wave Right Detected!");
                }
            });

        }
    }

    void OnDeviceOpened(object sende, EventArgs args)
    {
        //Do something when device is opened
        if (imiManager.IsDeviceOpened())
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            if (imiManager.IsPerformance)
            {
                colorView.transform.localScale = new Vector3(1, 1, 1);
            }
            else
            {
                colorView.transform.localScale = new Vector3(1, -1, 1);
            }
#else

#endif
            colorView.texture = ImiManager.GetInstance().GetColorTexture();
            //colorView.texture = ImiManager.GetInstance().GetMainUserColorTexture();
            //colorView.texture = ImiManager.GetInstance().GetMainUserDepthTexture();
            //colorView.texture = ImiManager.GetInstance().GetSubUserDepthTexture();


            //depthView.texture = ImiManager.GetInstance().GetDepthTexture();
            depthView.texture = ImiManager.GetInstance().GetUserDepthTexture();
            //depthView.texture = ImiManager.GetInstance().GetSubUserDepthTexture();
            //depthView.texture = ImiManager.GetInstance().GetSubUserColorTexture();
            //depthView.texture = ImiManager.GetInstance().GetMainUserDepthTexture();

            //ImiGestureManager gestureManager = ImiGestureManager.GetInstance();
            if (CustomDepthDataProcessor)
            {
                ImiManager.GetInstance().SetDepthDataProcessor(depthDataProcessor);
                depthView.texture = customDepthTex;
            }

        }

    }

    public void OnMainPlayerChange(int oldControlId, int newControlId)
    {
        Debug.Log(" on main player change");
    }


    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.Escape))
        {
            Application.Quit();
        }
        if (!ImiManager.GetInstance().IsDeviceOpened())
        {
            return;
        }

        if (CustomDepthDataProcessor)
        {
            UpdateDepthTex();
        }

        Dictionary<int, ImiPlayerInfo> playerInfos = ImiManager.GetInstance().GetPlayerInfos();

        if (playerInfos.Count <= 0)
        {
            return;
        }
        List<int> keys = new List<int>(playerInfos.Keys);
        for (int i = 0; i < keys.Count; i++)
        {
            //Debug.Log("Control player is" + imiManager.GetControlPlayerId());
            if (keys[i] == imiManager.GetControlPlayerId())
            {
                ImiSkeleton[] skeletons = playerInfos[keys[i]].GetSkeletons();
                for (int j = 0; j < skeletonCount; j++)
                {
                    //Debug.Log("player pos is " + skeletons[j].position.ToString());
                    skeletonList[j].transform.position = skeletons[j].position;
                }
            }
        }
    }

    //自定义深度图绘制数据处理.
    void depthDataProcessor(ushort[] depthData)

    {
        if (textureReady)
        {
            return;
        }

        int usersMapSize = 640 * 480;
        int numOfPoints = 0;

        Array.Clear(usersHistogramMap, 0, usersHistogramMap.Length);
        Array.Clear(usersDepthColors, 0, usersDepthColors.Length);

        for (int i = 0; i < usersMapSize; i++)
        {
            usersHistogramMap[depthData[i] >> 3]++;
            numOfPoints++;
        }

        if (numOfPoints > 0)
        {
            for (int i = 1; i < usersHistogramMap.Length; i++)
            {
                usersHistogramMap[i] += usersHistogramMap[i - 1];
            }

            for (int i = 0; i < usersHistogramMap.Length; i++)
            {
                usersHistogramMap[i] = 1.0f - (usersHistogramMap[i] / numOfPoints);
            }
        }

        int controlPlayerId = imiManager.GetControlPlayerId();
        int subControlPlayerId = imiManager.GetSubPlayerId();
        for (int i = 0; i < usersMapSize; i++)
        {
            int tempPlayerIndex = depthData[i] & 7;
            int userDepth = depthData[i] >> 3;
            float histDepth = usersHistogramMap[userDepth];

            //此处只绘制出主要玩家和次要玩家
            if (tempPlayerIndex == controlPlayerId)
            {
                usersDepthColors[i * 4] = (byte)(255 * histDepth);
                usersDepthColors[i * 4 + 1] = (byte)(105 * histDepth);
                usersDepthColors[i * 4 + 2] = (byte)(180 * histDepth);
                usersDepthColors[i * 4 + 3] = 255;
            }
            else if (tempPlayerIndex == subControlPlayerId)
            {
                usersDepthColors[i * 4] = (byte)(255 * histDepth);
                usersDepthColors[i * 4 + 1] = (byte)(215 * histDepth);
                usersDepthColors[i * 4 + 2] = (byte)(0 * histDepth);
                usersDepthColors[i * 4 + 3] = 255;
            }
            else
            {
                usersDepthColors[i * 4] = (byte)(125 * histDepth);
                usersDepthColors[i * 4 + 1] = (byte)(125 * histDepth);
                usersDepthColors[i * 4 + 2] = (byte)(125 * histDepth);
                usersDepthColors[i * 4 + 3] = 255;
            }
            //如果想绘制所有玩家，放开下面代码

            //switch (tempPlayerIndex)
            //{
            //    case 1:
            //        usersDepthColors[i * 4] = (byte)(255 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(105 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(180 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //    case 2:
            //        usersDepthColors[i * 4] = (byte)(255 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(0 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(255 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //    case 3:
            //        usersDepthColors[i * 4] = (byte)(255 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(105 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(180 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //    case 4:
            //        usersDepthColors[i * 4] = (byte)(148 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(0 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(211 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //    case 5:
            //        usersDepthColors[i * 4] = (byte)(0 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(0 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(255 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //    case 6:
            //        usersDepthColors[i * 4] = (byte)(255 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(215 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(0 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //    default:
            //        usersDepthColors[i * 4] = (byte)(125 * histDepth);
            //        usersDepthColors[i * 4 + 1] = (byte)(125 * histDepth);
            //        usersDepthColors[i * 4 + 2] = (byte)(125 * histDepth);
            //        usersDepthColors[i * 4 + 3] = 255;
            //        break;
            //}
        }

        textureReady = true;

    }

    private bool textureReady = false;
    private void UpdateDepthTex()
    {
        if (textureReady)
        {
            customDepthTex.LoadRawTextureData(usersDepthColors);
            customDepthTex.Apply();

            textureReady = false;
        }
    }

    public void OpenDevice()
    {
        Debug.Log("Opening Device!:");
        ImiManager.GetInstance().OpenDevice();
    }

    public void CloseDevice()
    {
        Debug.Log("Closing Device!");
        ImiManager.GetInstance().CloseDevice();
    }

}
